#include <QMetaObject>
#include <QMetaProperty>
#include <QList>
#include <qqmlregistration.h>
#include <QQuickItem>
#include <QDebug>
#include <QQmlContext>
#include "IdHacker.h"

void IdHacker::setTarget(QObject *target)
{
    if(m_target != target)
    {
        m_target = target;
        update();
        emit targetChanged();
    }
}

QObject *IdHacker::target()
{
    return m_target;
}

IdHacker::IdHacker()
{

}

IdHacker::~IdHacker()
{

}

static void hack_imp(QObject* root,QMap<QString,int>& datas,QMap<QString,QObject*> &output,IdHacker* hacker){

    auto ctx = qmlContext(root);

    if(ctx)
    {
        QString name = ctx->nameForObject(root);//检查该对象在它自己的上下文中是什么名称

        if(!name.isEmpty())
        {
            if(datas.contains(name))
            {
                QMetaType targetType = QMetaType(datas[name]);
                QMetaType srcType = QMetaType::fromName(QString(QString(root->metaObject()->metaType().name()) + "*").toUtf8());

                if(targetType.id() == QMetaType::QVariant || QMetaType::canConvert(srcType,targetType))
                {
                    datas.remove(name);
                    output[name] = root;
                }
            }
        }
    }



    if(datas.empty())
    {
        return;
    }

    for(auto i:root->children())
    {
        hack_imp(i,datas,output,hacker);
        if(datas.empty())
        {
            return;
        }
    }
}

void IdHacker::update()
{
    if(!m_target)
    {
        return;
    }
    auto meta = metaObject();

    QMap<QString,int> datas;

    for(int i = IdHacker::metaObject()->propertyOffset();i<meta->propertyCount();i++)
    {
        auto property = meta->property(i);

        auto type = QMetaType(property.typeId());

        if(type.id() != QMetaType::QVariant)
        {
            if(!(type.flags() & (QMetaType::PointerToQObject)))
            {
                continue;
            }
        }

        datas[property.name()] = property.typeId();
    }

    QMap<QString,QObject*> output;

    for(auto i:datas.keys())
    {
        output[i] = nullptr;
    }

    hack_imp(m_target,datas,output,this);

    for(auto i:output.keys())
    {
        setProperty(i.toUtf8(),QVariant::fromValue(output[i]));
    }
}
